package module

// 要监听端口, 与客户端/另一进程交互的核心

import (
	"go.uber.org/zap"
	"gogogo-server/engine/cororpc"
	"gogogo-server/engine/lgconf"
	"gogogo-server/engine/network/codec"
	"gogogo-server/engine/network/codec/json"
	"gogogo-server/engine/network/codec/msgpack"
	"gogogo-server/engine/network/netproc"
	"gogogo-server/engine/network/netproc/ws"
)

// LGNetworkNode 网络管理节点
type LGNetworkNode struct {
	ClientCfg    *lgconf.LGClientConfig
	ServerCfg    *lgconf.LGServerConfig
	MsgProcessor codec.IMsgProcessor
	NetProc      netproc.INetProcess
}

func (n *LGNetworkNode) GetName() string {
	if n.ClientCfg != nil {
		return n.ClientCfg.Name
	} else {
		return n.ServerCfg.Name
	}
}

// LGGate 网关
type LGGate struct {
	clientMap map[string]*LGNetworkNode
	serverMap map[string]*LGNetworkNode
}

var gLGGate LGGate

func GateInstance() *LGGate {
	gLGGate.clientMap = make(map[string]*LGNetworkNode)
	gLGGate.serverMap = make(map[string]*LGNetworkNode)
	for _, c := range lgconf.LGConfig.Clients {
		gLGGate.RegisterClient(&c)
	}
	for _, c := range lgconf.LGConfig.Servers {
		gLGGate.RegisterServer(&c)
	}
	return &gLGGate
}

func getLGNetworkNode(msgProcessType string) codec.IMsgProcessor {
	switch msgProcessType {
	case "json":
		return json.NewProcessor()
	case "msgpack":
		return msgpack.NewProcessor()
	default:
		zap.S().Fatalf("计算消息处理器失败,消息处理器[%s]暂时不支持", msgProcessType)
	}
	return nil
}

func (gate *LGGate) RegisterClient(arg *lgconf.LGClientConfig) {
	if _, ok := gate.clientMap[arg.Name]; ok {
		zap.S().Fatalf("客户端:%s 重复注册", arg.Name)
	}
	gate.clientMap[arg.Name] = &LGNetworkNode{
		ClientCfg:    arg,
		MsgProcessor: getLGNetworkNode(arg.MsgProcType),
	}
}

func (gate *LGGate) RegisterServer(arg *lgconf.LGServerConfig) {
	if _, ok := gate.serverMap[arg.Name]; ok {
		zap.S().Fatalf("服务端:%s 重复注册", arg.Name)
	}
	gate.serverMap[arg.Name] = &LGNetworkNode{
		ServerCfg:    arg,
		MsgProcessor: getLGNetworkNode(arg.MsgProcType),
	}
}

// GetClient 获取客户端网络管理
func (gate *LGGate) GetClient(name string) *LGNetworkNode {
	if rlt, ok := gate.clientMap[name]; ok {
		return rlt
	}
	return nil
}

// GetServer 获取服务端网络端处理
func (gate *LGGate) GetServer(name string) *LGNetworkNode {
	if rlt, ok := gate.serverMap[name]; ok {
		return rlt
	}
	return nil
}

func (gate *LGGate) Run(closeSig chan bool) {
	for _, v := range gate.clientMap {
		switch v.ClientCfg.NetworkType {
		case "ws":
			v.NetProc = ws.NewClient(v.ClientCfg, func(conn netproc.IConn) cororpc.IGateAgent {
				a := newAgent(conn, v)
				v.MsgProcessor.Route(&cororpc.BaseMessageArg{
					MsgId: "NewAgent",
					Agent: a,
				})
				zap.S().Debugf("[%s] 有新的连接成功,local:%s, remote:%s", v.ClientCfg.Name, a.LocalAddr(), a.RemoteAddr())
				return a
			})
		}
	}
	for _, v := range gate.serverMap {
		switch v.ServerCfg.NetworkType {
		case "ws":
			v.NetProc = ws.NewServer(v.ServerCfg, func(conn netproc.IConn) cororpc.IGateAgent {
				a := newAgent(conn, v)
				v.MsgProcessor.Route(&cororpc.BaseMessageArg{
					MsgId: "NewAgent",
					Agent: a,
				})
				zap.S().Debugf("[%s] 有新的连接成功,local:%s, remote:%s", v.ServerCfg.Name, a.LocalAddr(), a.RemoteAddr())
				return a
			})
		}
	}
	gate.run(closeSig)
}

func (gate *LGGate) run(closeSig chan bool) {
	for _, v := range gate.clientMap {
		v.NetProc.Start()
	}
	for _, v := range gate.serverMap {
		v.NetProc.Start()
	}
	<-closeSig
	for _, v := range gate.clientMap {
		v.NetProc.Close()
	}
	for _, v := range gate.serverMap {
		v.NetProc.Close()
	}
}

func (gate *LGGate) Destroy() {}

type agent struct {
	conn        netproc.IConn
	netNode     *LGNetworkNode
	sendMsgChan chan cororpc.IMessageArg
	ud          any
}

func newAgent(conn netproc.IConn, node *LGNetworkNode) *agent {
	return &agent{
		conn:        conn,
		netNode:     node,
		sendMsgChan: make(chan cororpc.IMessageArg),
	}
}

// AgentRun 在连接连上来的息怕协程里面一直run
func (a *agent) AgentRun() {
	go func() {
		for msg := range a.sendMsgChan {
			if data, err := a.netNode.MsgProcessor.Marshal(msg); err != nil {
				a.conn.WriteMsg(data)
			}
		}
	}()
	for {
		data, err := a.conn.ReadMsg()
		if err != nil {
			zap.S().Debugf("[%s] Local:%s Remote:%s 读取消失出错:%s",
				a.netNode.GetName(), a.LocalAddr(), a.RemoteAddr(), err)
			break
		}
		if a.netNode.MsgProcessor != nil {
			msg, err := a.netNode.MsgProcessor.Unmarshal(data)
			if err != nil {
				zap.S().Warnf("解码出错:%s", err)
				break
			}
			msg.SetAgent(a)
			if err = a.netNode.MsgProcessor.Route(msg); err != nil {
				zap.S().Warnf("消息:%T转发出错:%s", msg, err)
				break
			}
		}
	}
}

func (a *agent) LocalAddr() string {
	return a.conn.LocalAddr()
}

func (a *agent) RemoteAddr() string {
	return a.conn.RemoteAddr()
}

func (a *agent) AgentClose() {
	a.netNode.MsgProcessor.Route(&cororpc.BaseMessageArg{
		MsgId: "CloseAgent",
		Agent: a,
	})
	close(a.sendMsgChan)
}

func (a *agent) SendMsg(arg cororpc.IMessageArg) error {
	select {
	case a.sendMsgChan <- arg:
	default:
		zap.S().Debugf("发送失败")
	}
	return nil
}

func (a *agent) SetUserData(ud any) {
	a.ud = ud
}

func (a *agent) GetUserData() any {
	return a.ud
}
